﻿// Copyright (c) Inossem. All rights reserved.
// Licensed under the LGPL-3.0 license. See LICENSE file in the project root for full license information.
using DWF.Studio.Custom;
using DWF.Studio.ISerivces;
using DWF.Studio.Models;
using DWF.Studio.Project;
using DWF.Studio.Share.Log;
using DWF.Studio.Share.Serialization;
using DWF.Studio.Share.Utils;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DWF.Studio.Services
{
    internal class ProjectSettingService : IProjectSettingService
    {
        private ProjectManager _projectManager = null;
        public ProjectSettingService()
        {
            _projectManager = ProjectManager.Instance;
        }

        public IEnumerable<Breakpoint> GetBreakpoints(string filePath)
        {
            List<Breakpoint> breakpoints = null;
            if (_projectManager.CurrentProject != null)
            {
                var projectPath = _projectManager.CurrentProject.FullName;
                var setting = getSetting(projectPath);
                if (setting.Breakpoints == null)
                {
                    setting.Breakpoints = new List<Breakpoint>();
                    saveSetting(projectPath, setting);
                }
                else
                {
                    breakpoints = setting.Breakpoints.Where(item => item.Path == filePath).ToList();
                }
            }

            return breakpoints;
        }
        public IEnumerable<Breakpoint> GetBreakpointsAll(IEnumerable<Script.ScriptBase> scriptBase)
        {
            var _projectManager = ProjectManager.Instance;
            List<Breakpoint> breakpoints = new List<Breakpoint>();
            var fileNode = _projectManager.CurrentProject.Children.FirstOrDefault(item => item.NodeType == EProjectNodeType.Folder && item.Name == StaticResource.ProjectSelfFile);
            var files = fileNode.Children.Select(item => item as ProjectFile);
            foreach (var item in files)
            {
                var points = this.GetBreakpoints(item.FullName);
                foreach (var point in points)
                {
                    var breakpointModel = point;
                    if (point.BreakpointType== 1)
                    {
                        breakpointModel.BreakpointViewTypeUri = new Uri("../Resources/StatusBar/enable.png", UriKind.Relative);
                    }
                    else if (point.BreakpointType==2)
                    {
                        breakpointModel.BreakpointViewTypeUri= new Uri("../Resources/StatusBar/disable.png", UriKind.Relative);
                    }
                    breakpointModel.FileName = System.IO.Path.GetFileName(point.Path);
                    breakpoints.Add(breakpointModel);
                }
            }
            if (breakpoints.Count > 0)
                return breakpoints;
            else
                return null;
        }
        public void AddBreakpoint(Breakpoint breakpoint)
        {
            if (_projectManager.CurrentProject != null)
            {
                var projectPath = _projectManager.CurrentProject.FullName;
                var setting = getSetting(projectPath);
                if (setting.Breakpoints == null)
                {
                    setting.Breakpoints = new List<Breakpoint>();
                }
                else
                {
                    var bps = setting.Breakpoints.Where(item => (item.Path == breakpoint.Path && (!String.IsNullOrWhiteSpace(item.ActivityId)) && item.ActivityId == breakpoint.ActivityId && (!String.IsNullOrWhiteSpace(item.ActivityType)) && item.ActivityType == breakpoint.ActivityType) || (item.Path == breakpoint.Path && (!String.IsNullOrWhiteSpace(item.Location)) && item.Location == breakpoint.Location));
                    setting.Breakpoints.RemoveAll(item => bps.Any((bp) => item == bp));
                }

                setting.Breakpoints.Add(breakpoint);
                saveSetting(projectPath, setting);
            }
        }

        public void UpdateBreakpoint(Breakpoint breakpoint)
        {
            if (_projectManager.CurrentProject != null)
            {
                var projectPath = _projectManager.CurrentProject.FullName;
                var setting = getSetting(projectPath);
                if (setting.Breakpoints == null)
                {
                    setting.Breakpoints = new List<Breakpoint>();
                }
                else
                {
                    var bps = setting.Breakpoints.Where(item => (item.Path == breakpoint.Path && (!String.IsNullOrWhiteSpace(item.ActivityId)) && item.ActivityId == breakpoint.ActivityId && (!String.IsNullOrWhiteSpace(item.ActivityType)) && item.ActivityType == breakpoint.ActivityType) || (item.Path == breakpoint.Path && (!String.IsNullOrWhiteSpace(item.Location)) && item.Location == breakpoint.Location));
                    setting.Breakpoints.RemoveAll(item => bps.Any((bp) => item == bp));

                    setting.Breakpoints.Add(breakpoint);
                }

                saveSetting(projectPath, setting);
            }
        }
        /// <summary>
        /// 全部禁用/启用
        /// </summary>
        /// <param name="breakpoint"></param>
        public IEnumerable<Breakpoint> UpdateBreakpointAll(bool isEnable)
        {
            if (_projectManager.CurrentProject != null)
            {
                var _projectManager = ProjectManager.Instance;
                var projectPath = _projectManager.CurrentProject.FullName;
                var setting = getSetting(projectPath);
                if (setting.Breakpoints == null)
                {
                    setting.Breakpoints = new List<Breakpoint>();
                }
                else
                {
                    List<Breakpoint> bps = new List<Breakpoint>();
                    
                    foreach (var breakitem in setting.Breakpoints)
                    {
                        Breakpoint breakpoint = breakitem;
                        if (string.IsNullOrWhiteSpace(breakitem.Location))
                        {
                            breakpoint.BreakpointType = isEnable ? 1 : 2;
                        }
                        else
                        {
                            breakpoint.IsEnabled = isEnable;
                        }

                        bps.Add(breakpoint);
                    }
                    setting.Breakpoints.RemoveAll(item => 1 == 1);
                    bps.ForEach(o => setting.Breakpoints.Add(o));
                }
                
                saveSetting(projectPath, setting);
                return setting.Breakpoints;
            }
            return null;
        }
        public void RemoveBreakpoint(Breakpoint breakpoint)
        {
            if (_projectManager.CurrentProject != null)
            {
                var projectPath = _projectManager.CurrentProject.FullName;
                var setting = getSetting(projectPath);
                if (setting.Breakpoints == null)
                {
                    setting.Breakpoints = new List<Breakpoint>();
                }
                else
                {
                    var bps = setting.Breakpoints.Where(item => (item.Path == breakpoint.Path && (!String.IsNullOrWhiteSpace(item.ActivityId)) && item.ActivityId == breakpoint.ActivityId && (!String.IsNullOrWhiteSpace(item.ActivityType)) && item.ActivityType == breakpoint.ActivityType) || (item.Path == breakpoint.Path && (!String.IsNullOrWhiteSpace(item.Location)) && item.Location == breakpoint.Location));
                    setting.Breakpoints.RemoveAll(item => bps.Any((bp) => item == bp));
                }

                saveSetting(projectPath, setting);
            }
        }

        public void RemoveBreakpoints(string filePath)
        {
            if (_projectManager.CurrentProject != null)
            {
                var projectPath = _projectManager.CurrentProject.FullName;
                var setting = getSetting(projectPath);
                if (setting.Breakpoints == null)
                {
                    setting.Breakpoints = new List<Breakpoint>();
                }
                else
                {
                    var bps = setting.Breakpoints.Where(item => item.Path == filePath);
                    setting.Breakpoints.RemoveAll(item => bps.Any((bp) => item == bp));
                }

                saveSetting(projectPath, setting);
            }
        }
        public void RemoveAllBreakpoints()
        {
            if (_projectManager.CurrentProject != null)
            {
                var _projectManager = ProjectManager.Instance;
                var projectPath = _projectManager.CurrentProject.FullName;
                var setting = getSetting(projectPath);
                if (setting.Breakpoints == null)
                {
                    setting.Breakpoints = new List<Breakpoint>();
                }
                else
                {
                    var bps = setting.Breakpoints;
                    setting.Breakpoints.RemoveAll(item => bps.Any((bp) => item == bp));
                }
                saveSetting(projectPath, setting);
            }
        }
        public void RefreshBreakpoints(string filePath, IEnumerable<Breakpoint> breakpoints)
        {
            if (_projectManager.CurrentProject != null && breakpoints != null)
            {
                var projectPath = _projectManager.CurrentProject.FullName;
                var setting = getSetting(projectPath);
                if (setting.Breakpoints == null)
                {
                    setting.Breakpoints = new List<Breakpoint>();
                    setting.Breakpoints.AddRange(breakpoints);
                }
                else
                {
                    var bps = setting.Breakpoints.Where(item => item.Path == filePath);
                    setting.Breakpoints.RemoveAll(item => bps.Any((bp) => item == bp));
                    setting.Breakpoints.AddRange(breakpoints);
                }

                saveSetting(projectPath, setting);
            }
        }

        public void ChangeFilePath(string filePath, string newPath)
        {
            if (_projectManager.CurrentProject != null)
            {
                var projectPath = _projectManager.CurrentProject.FullName;
                var setting = getSetting(projectPath);
                if (setting.Breakpoints == null)
                {
                    setting.Breakpoints = new List<Breakpoint>();
                }
                else
                {
                    var bps = setting.Breakpoints.Where(item => item.Path == filePath);
                    foreach (var bp in bps)
                    {
                        bp.Path = newPath;
                    }
                }

                saveSetting(projectPath, setting);
            }
        }

        public IEnumerable<OpenedFile> GetOpenedFiles()
        {
            List<OpenedFile> openedFiles = null;

            var projectManager = ProjectManager.Instance;
            if (projectManager != null && projectManager.CurrentProject != null)
            {
                var projectPath = projectManager.CurrentProject.FullName;
                var setting = getSetting(projectPath);

                if (setting.OpenedFiles != null)
                {
                    openedFiles = setting.OpenedFiles.ToList();
                }
            }
            return openedFiles;
        }

        public void SetOpenedFiles(IEnumerable<OpenedFile> openedFiles)
        {
            if (_projectManager.CurrentProject != null)
            {
                var projectPath = _projectManager.CurrentProject.FullName;
                var setting = getSetting(projectPath);

                setting.OpenedFiles = new List<OpenedFile>();
                setting.OpenedFiles.AddRange(openedFiles);

                saveSetting(projectPath, setting);
            }
        }

        private ProjectSetting getSetting(string projectPath)
        {
            var settingPath = System.IO.Path.Combine(projectPath, StaticResource.ProjectSetting);

            ProjectSetting setting = null;

            if (FileHelper.CheckFileExisting(settingPath))//检查配置文件是否存在，如果存在这加载，否者新建。
            {
                setting = YamlHelper.Load<ProjectSetting>(settingPath, true);
            }

            if (setting == null)
            {
                setting = new ProjectSetting();
                saveSetting(projectPath, setting);
            }

            return setting;
        }

        private void saveSetting(string projectPath, ProjectSetting setting)
        {
            var settingPath = System.IO.Path.Combine(projectPath, StaticResource.ProjectSetting);

            YamlHelper.Save(setting, settingPath, true);
        }
    }
}
